﻿using System.Windows.Data;
using DimensionsHelper.Client.ViewModels.Message;
using DimensionsHelper.Common.Contracts;
using DimensionsHelper.Common.Contracts.Services;

namespace DimensionsHelper.Client.ViewModels.TaskPanel;

public partial class TaskViewModel : ObservableObject, IReportService
{

    public TaskViewModel(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
        BindingOperations.EnableCollectionSynchronization(Messages, Lock);
    }


    private static readonly object Lock = new();
    private readonly IServiceProvider _serviceProvider;


    [ObservableProperty]
    private bool _canRemove;


    [ObservableProperty]
    private bool _isTaskRunning;


    [ObservableProperty]
    private MessageViewModel? _lastMessage;


    [ObservableProperty]
    private ReportLevel _reportLevel = DimensionsHelper.Common.Contracts.ReportLevel.Brief;


    [ObservableProperty]
    private string _section = string.Empty;

    private Task? _task;


    [ObservableProperty]
    private string _taskId = string.Empty;

    private CancellationTokenSource? _tokenSource;


    public bool CanCancelTask => IsTaskRunning && _tokenSource is { Token.CanBeCanceled: true };


    public ObservableCollection<MessageViewModel> Messages { get; } = [];


    public bool CanClearMessages => !IsTaskRunning && Messages.Count > 0;

    public event Action<TaskViewModel>? RemoveSelf;


    [RelayCommand(CanExecute = nameof(CanRemove))]
    private void Remove()
    {
        RemoveSelf?.Invoke(this);
    }


    [RelayCommand(CanExecute = nameof(CanCancelTask))]
    public void Cancel()
    {
        _tokenSource?.Cancel();
        IsTaskRunning = false;
    }


    public void StartTask(Action<CancellationToken> taskCallback)
    {
        _task?.Dispose();
        _tokenSource?.Dispose();

        _tokenSource = new CancellationTokenSource();
        _task = new Task(() => taskCallback(_tokenSource.Token));
        _task.ContinueWith(_ =>
        {
            IsTaskRunning = false;
            _tokenSource.Dispose();
            _task.Dispose();
        });

        _task.Start();
        IsTaskRunning = true;
    }


    [RelayCommand(CanExecute = nameof(CanClearMessages))]
    private void ClearMessages()
    {
        Messages.Clear();
    }


    private void AddMessage(ReportMessageType type, string format, params object?[] args)
    {
        LastMessage = _serviceProvider.GetRequiredService<MessageViewModel>();
        LastMessage.Section = Section;
        LastMessage.Message = string.Format(format, args);
        LastMessage.MessageType = type;
        Messages.Add(LastMessage);
    }


    public void Log(string format, params object?[] args)
    {
        AddMessage(ReportMessageType.Info, format, args);
    }

    public void Log(ReportLevel level, string format, params object?[] args)
    {
        if (level == ReportLevel.Detail && ReportLevel == ReportLevel.Brief)
        {
            return;
        }

        Log(format, args);
    }

    public void Warn(string format, params object?[] args)
    {
        AddMessage(ReportMessageType.Warn, format, args);
    }

    public void Error(string format, params object?[] args)
    {
        AddMessage(ReportMessageType.Error, format, args);
    }


    public void Progress(double progress)
    {
        // 更新进度条
        if (!double.IsNaN(progress))
        {
            // 如果上一个记录的进度是NAN，表示上一个记录不包含进度，如果>=100，表示上一个进度已结束。
            if (LastMessage is not { IsReportingProgress: true } or { IsProgressFinished: true })
            {
                LastMessage = _serviceProvider.GetRequiredService<MessageViewModel>();
                LastMessage.Section = Section;
                LastMessage.Progress = progress;
                LastMessage.IsReportingProgress = true;
                Messages.Add(LastMessage);
            }
            else
            {
                LastMessage.Progress = progress;
            }
        }
    }

    public void Progress(double progress, string format, params object?[] args)
    {
        // 更新进度条
        if (!double.IsNaN(progress))
        {
            // 如果上一个记录的进度是NAN，表示上一个记录不包含进度，如果>=100，表示上一个进度已结束。
            if (LastMessage is not { IsReportingProgress: true } or { IsProgressFinished: true })
            {
                LastMessage = _serviceProvider.GetRequiredService<MessageViewModel>();
                LastMessage.Section = Section;
                LastMessage.Message = string.Format(format, args);
                LastMessage.Progress = progress;
                LastMessage.IsReportingProgress = true;
                Messages.Add(LastMessage);
            }
            else
            {
                LastMessage.Message = string.Format(format, args);
                LastMessage.Progress = progress;
            }
        }
    }

    public void Directory(string localDirectory)
    {
        Directory(localDirectory, "");
    }

    public void Directory(string localDirectory, string format, params object?[] args)
    {
        LastMessage = _serviceProvider.GetRequiredService<MessageViewModel>();
        LastMessage.Section = Section;
        LastMessage.Message = string.Format(format, args);
        LastMessage.MessageType = ReportMessageType.Info;
        LastMessage.LocalPath = localDirectory;
        Messages.Add(LastMessage);
    }

    public IProgressEnumerable<T> WithProgress<T>(IEnumerable<T> source, int length, Func<T, double, string>? messageGetter) => throw new NotImplementedException();
}